/*
 * CPrinter.h
 *
 *  Created on: Oct 29, 2013
 *      Author: m
 */

#ifndef CPRINTER_H_
#define CPRINTER_H_

#include <string>
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdarg>
#include <sstream>
#include "common/Exception.h"

namespace ipc
{

class CPrinter
{
private:

    static std::string s_header;

    static void print( struct _IO_FILE *stream, const char *fmt, va_list arg_list )
    {
        std::string error;
        std::string mensajeBase;
        char *mostrar;
        size_t needed;
        unsigned int bufferSize;

        if ( (CPrinter::s_header).empty() == false )
        {
            mensajeBase = CPrinter::s_header;
            mensajeBase.append( ": " );
        }
        mensajeBase.append( fmt );
        mensajeBase.append( ".\n" );


        bufferSize = sizeof( char ) * ( 1024 + mensajeBase.length() );
        mostrar = (char*) malloc( bufferSize );

        if ( mostrar == NULL )
        {
            error = strerror( errno );
            throw Exception( "CPrinter Error: " + error );
        }

        needed = vsnprintf( mostrar, bufferSize, mensajeBase.c_str(),
                arg_list) + 1;

        if ( needed > bufferSize )
        {
            mostrar = (char*)realloc( (void*)mostrar, needed * sizeof(char) );

            if ( mostrar == NULL )
            {
                error = strerror( errno );
                throw Exception( "CPrinter Error: " + error );
            }

            vsnprintf( mostrar, sizeof( mostrar ), mensajeBase.c_str(),
                    arg_list);
        }

        write( fileno( stream ), mostrar, strlen( mostrar ) );
    }

    CPrinter();

public:
    virtual ~CPrinter();

    static void setHeader( const std::string &header )
    {
        CPrinter::s_header = header;
    }

    static void setHeader( const std::string &header, int identifier )
    {
        std::stringstream ss;

        ss << header << " " << identifier;

        CPrinter::s_header = ss.str();
    }

    static void printOut( const char *fmt, ... )
    {
        va_list arg_list;
        va_start(arg_list, fmt);

        CPrinter::print( stdout, fmt, arg_list );

        va_end( arg_list );
    }

    static void printErr( const char *fmt, ... )
    {
        va_list arg_list;
        va_start(arg_list, fmt);

        CPrinter::print( stderr, fmt, arg_list );

        va_end( arg_list );
    }

};

} /* namespace ipc */
#endif /* CPRINTER_H_ */
